package hu.ikti.gateway.impl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;

import hu.ikti.gateway.Activator;
import hu.ikti.gateway.webservice.classes.GwSyncService;
import hu.ikti.gateway.webservice.classes.GwSyncService_Service;
import hu.ikti.gateway.webservice.classes.MappedBundle;
import hu.ikti.gateway.webservice.classes.SyncRequest;
import hu.ikti.gateway.webservice.classes.SyncResponse;

public class WebserviceHandler {

	public static WebserviceHandler webservicehandler;
	private Long period;
	private Timer timer;
	private ResourceManager resourcemanager;
	
	String BundlePath = "/media/sda7/dev/";
	String ResPath;
	
	private WebserviceHandler() {
		period = new Long (2000);
		resourcemanager = ResourceManager.getInstance();
		initTimer();
	}
	
	public void initTimer() {
		
		if (period == null) {
			CustomLogService.error("nincs kitoltve a periodus");
			return;
		} else
			CustomLogService.info("periodusido: " + period);
		
		if (timer != null) {
			timer.cancel();
			timer = null;
		}
		
		if (timer == null) {
			synchronized (WebserviceHandler.class) {
				TimerTask timertask = new TimerTask() {
					
					@Override
					public void run() {
						
						CustomLogService.info("gateway-server bundle sync started");
						try {
							handle();
						} catch (Exception e) {
							CustomLogService.error("unexpected error");
							e.printStackTrace();
						}
					}
				};
				System.out.println("starting...");
				timer = new Timer();
				timer.schedule(timertask, 0, period);
			}
		}
	}
	
	public static WebserviceHandler getInstance() throws Exception {
		if (webservicehandler == null) {
			synchronized (WebserviceHandler.class) {
				return webservicehandler = new WebserviceHandler();
			}
		} else
			return webservicehandler;
		
	}
	
	public void handle() throws Exception{
		SyncRequest request = new SyncRequest();

		Bundle[] bundles = Activator.getContext().getBundles();

		for (Bundle bundle : bundles) {
			MappedBundle temp = new MappedBundle();
			temp.setSymbolicName(bundle.getSymbolicName());
			//temp.setVersion( bundle.getVersion());
			request.getRequestList().add(temp);
		}
		
		CustomLogService.info("uploading data about " + request.getRequestList().size() + " bundles...");
        GwSyncService_Service service1 = new GwSyncService_Service();
        GwSyncService port1 = service1.getGwSyncServicePort();
		SyncResponse response = port1.synchronise(request);
		CustomLogService.info("downloaded "+response.getResponseList().size() + " new bundles.");
		
		List<String[]> bundleList = new ArrayList<String[]>();
		
		for (MappedBundle mappedbundle : response.getResponseList()){
			String[] temp = {mappedbundle.getSymbolicName(), resourcemanager.makeRes(mappedbundle.getBytecode(), mappedbundle.getSymbolicName(), "jar")};
			bundleList.add(temp);
			CustomLogService.info("Jar created: " + mappedbundle.getSymbolicName());
		}
		updateBundles(bundleList);
		
	}
	
	/**
	 * This method updates or installs bundles. 
	 * @param jarList - a string array, containing the names and paths of jars.
	 * @param bc - the current bundlecontext.
	 */
	public void updateBundles(List<String[]> jarList) {
		
		ArrayList<Long> installedbundles = new ArrayList<Long>();
		
		try {
			Bundle[] currentBundles = Activator.getContext().getBundles();
			
			for (int i = 0; i < jarList.size(); i++) {
				boolean tempUdpated = false;
				String[] tempBundleInfo = jarList.get(i);
				
				for (int j = 0; j < currentBundles.length; j++) {
					
					if (tempBundleInfo[0].equals(currentBundles[j].getSymbolicName())) {
						
						installedbundles.add(currentBundles[j].getBundleId());
						
						currentBundles[j].update(new FileInputStream(tempBundleInfo[1]));
						tempUdpated = true;
						CustomLogService.info("updated: " + tempBundleInfo[0]);
						
					}
				}
				if (!tempUdpated) {
					installedbundles.add((Activator.getContext().installBundle("file:///" + tempBundleInfo[1])).getBundleId());
					CustomLogService.info("installed: " + tempBundleInfo[0]);
				}
			}
			
			// starting bundles
			for (int i = 0; i < installedbundles.size(); i++) {
				Bundle temp = Activator.getContext().getBundle(installedbundles.get(i));
				if (temp.getState() != Bundle.ACTIVE)
					temp.start();
			}
			
		} catch (FileNotFoundException e) {
			CustomLogService.error(e.getMessage());
		} catch (BundleException e) {
			CustomLogService.error(e.getMessage());
			} 		
	}
}
